use honeybee::mongodb::bson;
use honeybee::prelude::*;
use honeybee::Result;

use crate::apps;

#[derive(Default)]
pub struct GmsgActor {
    apps_addr: Option<Addr<apps::Apps>>,
}

impl GmsgActor {
    fn apps_addr(&self) -> &Addr<apps::Apps> {
        self.apps_addr.as_ref().unwrap()
    }
}

impl Service for GmsgActor {}

#[async_trait::async_trait]
impl Actor for GmsgActor {
    fn name(&self) -> &str {
        "GmsgActor"
    }

    async fn started(&mut self, ctx: &mut Context<Self>) -> Result<()> {
        info!("{} started", self.name());
        let router = ctx.get_router().await?;
        router.register::<proto::GmsgForward>();

        self.apps_addr = apps::Apps::from_registry().await?.into();
        Ok(())
    }

    async fn stopped(&mut self, _ctx: &mut Context<Self>) {
        info!("{} stoped", self.name());
    }
}

#[async_trait::async_trait]
impl Handler<NetMsg<proto::GmsgForward>> for GmsgActor {
    async fn handle(
        &mut self,
        _ctx: &mut Context<Self>,
        msg: NetMsg<proto::GmsgForward>,
    ) -> Result<()> {
        let msg = msg.msg;
        let msg_doc = bson::Document::from_reader(&mut msg.msg_bytes.as_slice())?;
        let (object_id, expire_time) =
            gmsg_db::insert(msg.msg_type, msg_doc.clone(), msg.expire).await?;
        info!(
            "insert gmsg object_id:{} type:{:?} msg:{} expire:{:?} success",
            object_id, msg.msg_type, msg_doc, expire_time
        );
        let _ = self.apps_addr().send(apps::GmsgNotify {
            object_id: object_id.to_hex(),
            msg_type: msg.msg_type,
            msg_bytes: msg.msg_bytes,
            expire_time,
        });
        Ok(())
    }
}
